/* $Id: AdminNonClientPersonReviewFacadeImpl.java 
 * Copyright (C) 2011, TRAKHEES
 *  
 * Revision History
 *
 * Date  			Author 		    	Remarks
 * ---------------------------------------------------------------------------------
 *
 */
package ae.pcfc.etks.online.common.facade.provider;


import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.springframework.transaction.annotation.Transactional;

import ae.pcfc.etks.online.common.ConstantsCommon;
import ae.pcfc.etks.online.common.domain.AppMetaData;
import ae.pcfc.etks.online.common.domain.ClientPersonReq;
import ae.pcfc.etks.online.common.domain.ClientPersonRoleReq;
import ae.pcfc.etks.online.common.domain.TTscCity;
import ae.pcfc.etks.online.common.domain.TTscClientCategory;
import ae.pcfc.etks.online.common.domain.TTscClientRole;
import ae.pcfc.etks.online.common.domain.TTscCountry;
import ae.pcfc.etks.online.common.domain.TTscNametitle;
import ae.pcfc.etks.online.common.domain.TTscVisaType;
import ae.pcfc.etks.online.common.domain.manager.AppMetaDataDomainObjectManager;
import ae.pcfc.etks.online.common.domain.manager.NonClientPersonDomainObjectManager;
import ae.pcfc.etks.online.common.domain.manager.ProcessStepActionDomainObjectManager;
import ae.pcfc.etks.online.common.domain.manager.SingleClientPersonDomainObjectManager;
import ae.pcfc.etks.online.common.domain.manager.SingleClientRoleObjectManager;
import ae.pcfc.etks.online.common.domain.manager.UtilityDomainObjectManager;
import ae.pcfc.etks.online.common.exception.InvalidInputException;
import ae.pcfc.etks.online.common.facade.AdminNonClientPersonReviewFacade;
import ae.pcfc.etks.online.common.vo.AdminApprovalVO;
import ae.pcfc.etks.online.common.vo.NonClientPersonVO;
import ae.pcfc.etks.online.wf.ConstantsWF;
import ae.pcfc.etks.online.wf.service.client.NonClientWF;
import ae.pcfc.etks.online.wf.service.client.vo.NonClientCompleteStepVO;


public class AdminNonClientPersonReviewFacadeImpl  extends BaseFacade implements AdminNonClientPersonReviewFacade{
    /*
	 * Here we coordinate between the all interacting business domain objects
	 * (BO), transactions are maintained here. use case business validation are
	 * maintained here (that requires DB checks or retrieving data from DB)
	 */
	private NonClientPersonDomainObjectManager nonClientPersonDomainObjectManager;	
	private  SingleClientRoleObjectManager singleClientRoleObjectManager;
	private SingleClientPersonDomainObjectManager singleClientPersonDomainObjectManager;
	private AppMetaDataDomainObjectManager appMetaDataDomainObjectManager;
	private NonClientWF nonClientPersonWF;
	private UtilityDomainObjectManager utilityDomainObjectManager;
	private ProcessStepActionDomainObjectManager processStepActionDomainObjectManager;
	
	public ProcessStepActionDomainObjectManager getProcessStepActionDomainObjectManager() {
		return processStepActionDomainObjectManager;
	}

	public void setProcessStepActionDomainObjectManager(
			ProcessStepActionDomainObjectManager processStepActionDomainObjectManager) {
		this.processStepActionDomainObjectManager = processStepActionDomainObjectManager;
	}

	public void setSingleClientRoleObjectManager(
			SingleClientRoleObjectManager singleClientRoleObjectManager) {
		this.singleClientRoleObjectManager = singleClientRoleObjectManager;
	}

	public void setNonClientPersonDomainObjectManager(
			NonClientPersonDomainObjectManager nonClientPersonDomainObjectManager) {
		this.nonClientPersonDomainObjectManager = nonClientPersonDomainObjectManager;
	}

	public void setSingleClientPersonDomainObjectManager(
			SingleClientPersonDomainObjectManager singleClientPersonDomainObjectManager) {
		this.singleClientPersonDomainObjectManager = singleClientPersonDomainObjectManager;
	}

	public void setAppMetaDataDomainObjectManager(
			AppMetaDataDomainObjectManager appMetaDataDomainObjectManager) {
		this.appMetaDataDomainObjectManager = appMetaDataDomainObjectManager;
	}
	
	public void setNonClientPersonWF(NonClientWF nonClientPersonWF) {
		this.nonClientPersonWF = nonClientPersonWF;
	}
	
	public void setUtilityDomainObjectManager(UtilityDomainObjectManager utilityDomainObjectManager) {
		this.utilityDomainObjectManager = utilityDomainObjectManager;
	}

	@Transactional( readOnly = true )
	public NonClientPersonVO getNonClientPersonByApplicationId(String applicationId) {
		
		ClientPersonReq clientPersonReq =  nonClientPersonDomainObjectManager.getNonClientPersonByApplicationId(applicationId);
		
		if( clientPersonReq != null )
		{			
			NonClientPersonVO nonClientPersonVO = null;
			TTscClientRole tscClientRole = new TTscClientRole();
			List<String> clientRoleList = new ArrayList<String>();
			for (ClientPersonRoleReq personRole : clientPersonReq.getClientPersonRoleReqs())
			{				
				tscClientRole =  singleClientRoleObjectManager.getClientRoleByRoleId(personRole.getCsrReqId().toString());
				clientRoleList.add(tscClientRole.getCrDesc());
			}
			
			
			nonClientPersonVO = new NonClientPersonVO();
			getMapper().map(clientPersonReq, nonClientPersonVO);
			//getMapper().map(tscClientRole, nonClientPersonVO);
			nonClientPersonVO.setListRoleDisplay(clientRoleList);
			
			if(clientPersonReq.getCpCategory() != null)
			{
				TTscClientCategory clientCategory = this.singleClientPersonDomainObjectManager.getClientCategoryById(clientPersonReq.getCpCategory());
				getMapper().map(clientCategory, nonClientPersonVO);
			}
			
			if(clientPersonReq.getCpNametitle() != null )
			{
				TTscNametitle nametitle = this.utilityDomainObjectManager.getNameTitleById(clientPersonReq.getCpNametitle().longValue());
				getMapper().map(nametitle, nonClientPersonVO);
			}
			
			if(clientPersonReq.getCpCity() != null)
			{
				TTscCity city = this.utilityDomainObjectManager.getCityByCode(clientPersonReq.getCpCity());
				
				getMapper().map(city, nonClientPersonVO);
				
			}
			
			if(clientPersonReq.getCpCountry() != null)
			{
				TTscCountry country = this.utilityDomainObjectManager.getCountryByCode(clientPersonReq.getCpCountry());
				
				getMapper().map(country, nonClientPersonVO);
			}
			
			if(clientPersonReq.getCpVType() != null)
			{
				TTscVisaType visaType = this.utilityDomainObjectManager.getVisaTypeByCode(clientPersonReq.getCpVType());
				
				getMapper().map(visaType, nonClientPersonVO);
				
			}
			return nonClientPersonVO;
		}	
				
		return null;
	}

	/**
	 * reviewNonClientPerson
	 * @return 
	 * 
	 * @see ae.pcfc.etks.online.common.facade.AdminNonClientPersonReviewFacade#reviewNonClientPerson(ae.pcfc.etks.online.common.vo.AdminApprovalVO, java.lang.String)
	 * 
	 */
	@Transactional
	public NonClientCompleteStepVO reviewNonClientPerson(AdminApprovalVO adminApprovalVO, String strUserName) {
		AppMetaData appMetaData = appMetaDataDomainObjectManager.findByPrimaryKeyProcessAndStepCode(adminApprovalVO.getStrApplicationId().toString(), adminApprovalVO.getProcessCode().getProcessCode(), adminApprovalVO.getStrStepName());

		if (appMetaData != null) {
			/************ Storing Meta Data in Tables ***********************/
		    	if(appMetaDataDomainObjectManager.validateAppMetaDataWithStep(appMetaData,adminApprovalVO.getStrStepName())){
		    	    throw new InvalidInputException();
		    	}
					
			String wfStatusEn = appMetaData.getWfStatusEn();
			String wfStatusAr = appMetaData.getWfStatusAr();
			
			getMapper().map(adminApprovalVO, appMetaData);
			
			appMetaData.setWfStatusEn(wfStatusEn);
			appMetaData.setWfStatusAr(wfStatusAr);
			this.appMetaDataDomainObjectManager.updateAppMetaDataWithActionTaken(appMetaData, adminApprovalVO.getStrStepName());
			/************** End Store Meta Date ***************************/
			ClientPersonReq clientPersonReq =  nonClientPersonDomainObjectManager.getNonClientPersonByApplicationId(adminApprovalVO.getStrApplicationId());	
			clientPersonReq.setCpCreatedUser(StringUtils.remove(strUserName,ConstantsWF.USER_PREFIX));
			NonClientCompleteStepVO completeStepVO = getCompleteStepVO(adminApprovalVO, appMetaData, clientPersonReq, strUserName);

			if(nonClientPersonWF.getFinDeptStepName().equalsIgnoreCase(adminApprovalVO.getStrStepName()) && adminApprovalVO.getStrActionType().equals(ConstantsCommon.APPROVE)){
			    	// If Approved by Finance department, send the approval message to the Ultimus alone and update the application request in the DB as approved
					Map<String, String> valuesMap = singleClientPersonDomainObjectManager.add(clientPersonReq);
				    completeStepVO.setgTKSID(valuesMap.get(ConstantsCommon.TRAKHEES_ID));
				    completeStepVO.setgPin(valuesMap.get(ConstantsCommon.PIN_CODE));
				    //clientPersonReq.setCpStatus(adminApprovalVO.getStrActionType());
				    //nonClientPersonDomainObjectManager.update(clientPersonReq);
        			appMetaData.setWfStatus(ConstantsCommon.APPROVE);
        			appMetaData.setWfStatusEn(adminApprovalVO.getStrStatusEn());
        			appMetaData.setWfStatusAr(adminApprovalVO.getStrStatusAr());
        			nonClientPersonWF.updateCompleteStepVO(completeStepVO, adminApprovalVO.getStrStepName(), ConstantsCommon.WORK_FLOW_STATUS_APPROVE, adminApprovalVO.getStrUserNotification());
			}else if(adminApprovalVO.getStrActionType().equals(ConstantsCommon.APPROVE)){
			    	// If Approved by any other departments, send the approval message to the Ultimus alone
				nonClientPersonWF.updateCompleteStepVO(completeStepVO, adminApprovalVO.getStrStepName(), ConstantsCommon.WORK_FLOW_STATUS_APPROVE, adminApprovalVO.getStrUserNotification());
			}else if(adminApprovalVO.getStrActionType().equals(ConstantsCommon.REJECT)){
			    	// If Rejected, update the application request in DB as rejected and send the rejection message to the Ultimus
					//clientPersonReq.setCpStatus(ConstantsCommon.REJECT);
					//nonClientPersonDomainObjectManager.update(clientPersonReq);
			    	appMetaData.setWfStatus(ConstantsCommon.REJECT);
					appMetaData.setWfStatusEn(adminApprovalVO.getStrStatusEn());
					appMetaData.setWfStatusAr(adminApprovalVO.getStrStatusAr());
					nonClientPersonWF.updateCompleteStepVO(completeStepVO, adminApprovalVO.getStrStepName(), ConstantsCommon.WORK_FLOW_STATUS_REJECT, adminApprovalVO.getStrUserNotification());
			}
			appMetaDataDomainObjectManager.update(appMetaData);
			return completeStepVO;
		}
		
		return null;
	}
	private NonClientCompleteStepVO getCompleteStepVO(AdminApprovalVO adminApprovalVO, AppMetaData appMetaData,ClientPersonReq clientPersonReq, String strUserName) {
		NonClientCompleteStepVO completeStepVO = new NonClientCompleteStepVO();
		completeStepVO.setgApplicationID(adminApprovalVO.getStrApplicationId());
		completeStepVO.setgClientReference(appMetaData.getClientRefNo());
		completeStepVO.setStrStepName(adminApprovalVO.getStrStepName());
		completeStepVO.setStrUserName(adminApprovalVO.getStrUserName());
		completeStepVO.setgName(clientPersonReq.getCpNamEng());
		completeStepVO.setgEmail(clientPersonReq.getCpEmail());
		completeStepVO.setgCustomerMsg(adminApprovalVO.getStrUserNotification());
		completeStepVO.setnIncidentNumber(Integer.parseInt(adminApprovalVO.getStrIncidentNo()));
		return completeStepVO;
	}

	@Transactional
	public void undoReviewNonClientPerson(AdminApprovalVO adminApprovalVO, String strTrakheesId) {
		AppMetaData appMetaData = appMetaDataDomainObjectManager.findByPrimaryKeyProcessAndStepCode(adminApprovalVO
				.getStrApplicationId().toString(), adminApprovalVO.getProcessCode().getProcessCode(), adminApprovalVO.getStrStepName());

		if (appMetaData != null) {
			adminApprovalVO.setStrApplnStatus(ConstantsCommon.IN_PROGRESS);
			getMapper().map(adminApprovalVO, appMetaData);
			
			this.appMetaDataDomainObjectManager.undoUpdateAppMetaDataWithActionTaken(appMetaData, adminApprovalVO.getStrStepName());

			if(nonClientPersonWF.getFinDeptStepName().equalsIgnoreCase(adminApprovalVO.getStrStepName()) && adminApprovalVO.getStrActionType().equals(ConstantsCommon.APPROVE)){
			    	// If Approved by Finance department, send the approval message to the Ultimus alone and update the application request in the DB as approved
					ClientPersonReq clientPersonReq = nonClientPersonDomainObjectManager.getNonClientPersonByApplicationId(adminApprovalVO.getStrApplicationId());
					//clientPersonReq.setCpStatus(ConstantsCommon.CLIENT_STATUS_INACTIVE);
			    	this.singleClientPersonDomainObjectManager.undoCreatePerson(clientPersonReq, strTrakheesId, ConstantsCommon.CLIENT_STATUS_INACTIVE);
			    	//clientPersonReq.setCpStatus(ConstantsCommon.IN_PROGRESS);
			    	//nonClientPersonDomainObjectManager.update(clientPersonReq);
			}
			appMetaData.setWfStatus(ConstantsCommon.IN_PROGRESS);
			appMetaData.setWfStatusEn(adminApprovalVO.getStrInProgressStatusEn());
			appMetaData.setWfStatusAr(adminApprovalVO.getStrInProgressStatusAr());
			appMetaDataDomainObjectManager.update(appMetaData);
		}
	}
}